home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / python2.6 / aifc.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  28.9 KB  |  1,039 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''Stuff to parse AIFF-C and AIFF files.
  5.  
  6. Unless explicitly stated otherwise, the description below is true
  7. both for AIFF-C files and AIFF files.
  8.  
  9. An AIFF-C file has the following structure.
  10.  
  11.   +-----------------+
  12.   | FORM            |
  13.   +-----------------+
  14.   | <size>          |
  15.   +----+------------+
  16.   |    | AIFC       |
  17.   |    +------------+
  18.   |    | <chunks>   |
  19.   |    |    .       |
  20.   |    |    .       |
  21.   |    |    .       |
  22.   +----+------------+
  23.  
  24. An AIFF file has the string "AIFF" instead of "AIFC".
  25.  
  26. A chunk consists of an identifier (4 bytes) followed by a size (4 bytes,
  27. big endian order), followed by the data.  The size field does not include
  28. the size of the 8 byte header.
  29.  
  30. The following chunk types are recognized.
  31.  
  32.   FVER
  33.       <version number of AIFF-C defining document> (AIFF-C only).
  34.   MARK
  35.       <# of markers> (2 bytes)
  36.       list of markers:
  37.           <marker ID> (2 bytes, must be > 0)
  38.           <position> (4 bytes)
  39.           <marker name> ("pstring")
  40.   COMM
  41.       <# of channels> (2 bytes)
  42.       <# of sound frames> (4 bytes)
  43.       <size of the samples> (2 bytes)
  44.       <sampling frequency> (10 bytes, IEEE 80-bit extended
  45.           floating point)
  46.       in AIFF-C files only:
  47.       <compression type> (4 bytes)
  48.       <human-readable version of compression type> ("pstring")
  49.   SSND
  50.       <offset> (4 bytes, not used by this program)
  51.       <blocksize> (4 bytes, not used by this program)
  52.       <sound data>
  53.  
  54. A pstring consists of 1 byte length, a string of characters, and 0 or 1
  55. byte pad to make the total length even.
  56.  
  57. Usage.
  58.  
  59. Reading AIFF files:
  60.   f = aifc.open(file, \'r\')
  61. where file is either the name of a file or an open file pointer.
  62. The open file pointer must have methods read(), seek(), and close().
  63. In some types of audio files, if the setpos() method is not used,
  64. the seek() method is not necessary.
  65.  
  66. This returns an instance of a class with the following public methods:
  67.   getnchannels()  -- returns number of audio channels (1 for
  68.              mono, 2 for stereo)
  69.   getsampwidth()  -- returns sample width in bytes
  70.   getframerate()  -- returns sampling frequency
  71.   getnframes()    -- returns number of audio frames
  72.   getcomptype()   -- returns compression type (\'NONE\' for AIFF files)
  73.   getcompname()   -- returns human-readable version of
  74.              compression type (\'not compressed\' for AIFF files)
  75.   getparams() -- returns a tuple consisting of all of the
  76.              above in the above order
  77.   getmarkers()    -- get the list of marks in the audio file or None
  78.              if there are no marks
  79.   getmark(id) -- get mark with the specified id (raises an error
  80.              if the mark does not exist)
  81.   readframes(n)   -- returns at most n frames of audio
  82.   rewind()    -- rewind to the beginning of the audio stream
  83.   setpos(pos) -- seek to the specified position
  84.   tell()      -- return the current position
  85.   close()     -- close the instance (make it unusable)
  86. The position returned by tell(), the position given to setpos() and
  87. the position of marks are all compatible and have nothing to do with
  88. the actual position in the file.
  89. The close() method is called automatically when the class instance
  90. is destroyed.
  91.  
  92. Writing AIFF files:
  93.   f = aifc.open(file, \'w\')
  94. where file is either the name of a file or an open file pointer.
  95. The open file pointer must have methods write(), tell(), seek(), and
  96. close().
  97.  
  98. This returns an instance of a class with the following public methods:
  99.   aiff()      -- create an AIFF file (AIFF-C default)
  100.   aifc()      -- create an AIFF-C file
  101.   setnchannels(n) -- set the number of channels
  102.   setsampwidth(n) -- set the sample width
  103.   setframerate(n) -- set the frame rate
  104.   setnframes(n)   -- set the number of frames
  105.   setcomptype(type, name)
  106.           -- set the compression type and the
  107.              human-readable compression type
  108.   setparams(tuple)
  109.           -- set all parameters at once
  110.   setmark(id, pos, name)
  111.           -- add specified mark to the list of marks
  112.   tell()      -- return current position in output file (useful
  113.              in combination with setmark())
  114.   writeframesraw(data)
  115.           -- write audio frames without pathing up the
  116.              file header
  117.   writeframes(data)
  118.           -- write audio frames and patch up the file header
  119.   close()     -- patch up the file header and close the
  120.              output file
  121. You should set the parameters before the first writeframesraw or
  122. writeframes.  The total number of frames does not need to be set,
  123. but when it is set to the correct value, the header does not have to
  124. be patched up.
  125. It is best to first set all parameters, perhaps possibly the
  126. compression type, and then write audio frames using writeframesraw.
  127. When all frames have been written, either call writeframes(\'\') or
  128. close() to patch up the sizes in the header.
  129. Marks can be added anytime.  If there are any marks, ypu must call
  130. close() after all frames have been written.
  131. The close() method is called automatically when the class instance
  132. is destroyed.
  133.  
  134. When a file is opened with the extension \'.aiff\', an AIFF file is
  135. written, otherwise an AIFF-C file is written.  This default can be
  136. changed by calling aiff() or aifc() before the first writeframes or
  137. writeframesraw.
  138. '''
  139. import struct
  140. import __builtin__
  141. __all__ = [
  142.     'Error',
  143.     'open',
  144.     'openfp']
  145.  
  146. class Error(Exception):
  147.     pass
  148.  
  149. _AIFC_version = 0xA2805140L
  150. _skiplist = ('COMT', 'INST', 'MIDI', 'AESD', 'APPL', 'NAME', 'AUTH', '(c) ', 'ANNO')
  151.  
  152. def _read_long(file):
  153.     
  154.     try:
  155.         return struct.unpack('>l', file.read(4))[0]
  156.     except struct.error:
  157.         raise EOFError
  158.  
  159.  
  160.  
  161. def _read_ulong(file):
  162.     
  163.     try:
  164.         return struct.unpack('>L', file.read(4))[0]
  165.     except struct.error:
  166.         raise EOFError
  167.  
  168.  
  169.  
  170. def _read_short(file):
  171.     
  172.     try:
  173.         return struct.unpack('>h', file.read(2))[0]
  174.     except struct.error:
  175.         raise EOFError
  176.  
  177.  
  178.  
  179. def _read_string(file):
  180.     length = ord(file.read(1))
  181.     if length == 0:
  182.         data = ''
  183.     else:
  184.         data = file.read(length)
  185.     if length & 1 == 0:
  186.         dummy = file.read(1)
  187.     
  188.     return data
  189.  
  190. _HUGE_VAL = 1.79769e+308
  191.  
  192. def _read_float(f):
  193.     expon = _read_short(f)
  194.     sign = 1
  195.     if expon < 0:
  196.         sign = -1
  197.         expon = expon + 32768
  198.     
  199.     himant = _read_ulong(f)
  200.     lomant = _read_ulong(f)
  201.     if himant == himant and lomant == lomant:
  202.         pass
  203.     elif lomant == 0:
  204.         f = 0
  205.     elif expon == 32767:
  206.         f = _HUGE_VAL
  207.     else:
  208.         expon = expon - 16383
  209.         f = (himant * 0x100000000L + lomant) * pow(2, expon - 63)
  210.     return sign * f
  211.  
  212.  
  213. def _write_short(f, x):
  214.     f.write(struct.pack('>h', x))
  215.  
  216.  
  217. def _write_long(f, x):
  218.     f.write(struct.pack('>L', x))
  219.  
  220.  
  221. def _write_string(f, s):
  222.     if len(s) > 255:
  223.         raise ValueError('string exceeds maximum pstring length')
  224.     len(s) > 255
  225.     f.write(chr(len(s)))
  226.     f.write(s)
  227.     if len(s) & 1 == 0:
  228.         f.write(chr(0))
  229.     
  230.  
  231.  
  232. def _write_float(f, x):
  233.     import math
  234.     if x < 0:
  235.         sign = 32768
  236.         x = x * -1
  237.     else:
  238.         sign = 0
  239.     if x == 0:
  240.         expon = 0
  241.         himant = 0
  242.         lomant = 0
  243.     else:
  244.         (fmant, expon) = math.frexp(x)
  245.         if expon > 16384 or fmant >= 1:
  246.             expon = sign | 32767
  247.             himant = 0
  248.             lomant = 0
  249.         else:
  250.             expon = expon + 16382
  251.             if expon < 0:
  252.                 fmant = math.ldexp(fmant, expon)
  253.                 expon = 0
  254.             
  255.             expon = expon | sign
  256.             fmant = math.ldexp(fmant, 32)
  257.             fsmant = math.floor(fmant)
  258.             himant = long(fsmant)
  259.             fmant = math.ldexp(fmant - fsmant, 32)
  260.             fsmant = math.floor(fmant)
  261.             lomant = long(fsmant)
  262.     _write_short(f, expon)
  263.     _write_long(f, himant)
  264.     _write_long(f, lomant)
  265.  
  266. from chunk import Chunk
  267.  
  268. class Aifc_read:
  269.     
  270.     def initfp(self, file):
  271.         self._version = 0
  272.         self._decomp = None
  273.         self._convert = None
  274.         self._markers = []
  275.         self._soundpos = 0
  276.         self._file = Chunk(file)
  277.         if self._file.getname() != 'FORM':
  278.             raise Error, 'file does not start with FORM id'
  279.         self._file.getname() != 'FORM'
  280.         formdata = self._file.read(4)
  281.         if formdata == 'AIFF':
  282.             self._aifc = 0
  283.         elif formdata == 'AIFC':
  284.             self._aifc = 1
  285.         else:
  286.             raise Error, 'not an AIFF or AIFF-C file'
  287.         self._comm_chunk_read = formdata == 'AIFF'
  288.         while None:
  289.             self._ssnd_seek_needed = 1
  290.             
  291.             try:
  292.                 chunk = Chunk(self._file)
  293.             except EOFError:
  294.                 break
  295.  
  296.             chunkname = chunk.getname()
  297.             if chunkname == 'COMM':
  298.                 self._read_comm_chunk(chunk)
  299.                 self._comm_chunk_read = 1
  300.             elif chunkname == 'SSND':
  301.                 self._ssnd_chunk = chunk
  302.                 dummy = chunk.read(8)
  303.                 self._ssnd_seek_needed = 0
  304.             elif chunkname == 'FVER':
  305.                 self._version = _read_ulong(chunk)
  306.             elif chunkname == 'MARK':
  307.                 self._readmark(chunk)
  308.             elif chunkname in _skiplist:
  309.                 pass
  310.             else:
  311.                 raise Error, 'unrecognized chunk type ' + chunk.chunkname
  312.             continue
  313.             if not (self._comm_chunk_read) or not (self._ssnd_chunk):
  314.                 raise Error, 'COMM chunk and/or SSND chunk missing'
  315.             not (self._ssnd_chunk)
  316.             if self._aifc and self._decomp:
  317.                 import cl
  318.                 params = [
  319.                     cl.ORIGINAL_FORMAT,
  320.                     0,
  321.                     cl.BITS_PER_COMPONENT,
  322.                     self._sampwidth * 8,
  323.                     cl.FRAME_RATE,
  324.                     self._framerate]
  325.                 if self._nchannels == 1:
  326.                     params[1] = cl.MONO
  327.                 elif self._nchannels == 2:
  328.                     params[1] = cl.STEREO_INTERLEAVED
  329.                 else:
  330.                     raise Error, 'cannot compress more than 2 channels'
  331.                 (self._nchannels == 1)._decomp.SetParams(params)
  332.             
  333.  
  334.     
  335.     def __init__(self, f):
  336.         if type(f) == type(''):
  337.             f = __builtin__.open(f, 'rb')
  338.         
  339.         self.initfp(f)
  340.  
  341.     
  342.     def getfp(self):
  343.         return self._file
  344.  
  345.     
  346.     def rewind(self):
  347.         self._ssnd_seek_needed = 1
  348.         self._soundpos = 0
  349.  
  350.     
  351.     def close(self):
  352.         if self._decomp:
  353.             self._decomp.CloseDecompressor()
  354.             self._decomp = None
  355.         
  356.         self._file = None
  357.  
  358.     
  359.     def tell(self):
  360.         return self._soundpos
  361.  
  362.     
  363.     def getnchannels(self):
  364.         return self._nchannels
  365.  
  366.     
  367.     def getnframes(self):
  368.         return self._nframes
  369.  
  370.     
  371.     def getsampwidth(self):
  372.         return self._sampwidth
  373.  
  374.     
  375.     def getframerate(self):
  376.         return self._framerate
  377.  
  378.     
  379.     def getcomptype(self):
  380.         return self._comptype
  381.  
  382.     
  383.     def getcompname(self):
  384.         return self._compname
  385.  
  386.     
  387.     def getparams(self):
  388.         return (self.getnchannels(), self.getsampwidth(), self.getframerate(), self.getnframes(), self.getcomptype(), self.getcompname())
  389.  
  390.     
  391.     def getmarkers(self):
  392.         if len(self._markers) == 0:
  393.             return None
  394.         return self._markers
  395.  
  396.     
  397.     def getmark(self, id):
  398.         for marker in self._markers:
  399.             if id == marker[0]:
  400.                 return marker
  401.         
  402.         raise Error, 'marker %r does not exist' % (id,)
  403.  
  404.     
  405.     def setpos(self, pos):
  406.         if pos < 0 or pos > self._nframes:
  407.             raise Error, 'position not in range'
  408.         pos > self._nframes
  409.         self._soundpos = pos
  410.         self._ssnd_seek_needed = 1
  411.  
  412.     
  413.     def readframes(self, nframes):
  414.         if self._ssnd_seek_needed:
  415.             self._ssnd_chunk.seek(0)
  416.             dummy = self._ssnd_chunk.read(8)
  417.             pos = self._soundpos * self._framesize
  418.             if pos:
  419.                 self._ssnd_chunk.seek(pos + 8)
  420.             
  421.             self._ssnd_seek_needed = 0
  422.         
  423.         if nframes == 0:
  424.             return ''
  425.         data = self._ssnd_chunk.read(nframes * self._framesize)
  426.         if self._convert and data:
  427.             data = self._convert(data)
  428.         
  429.         self._soundpos = self._soundpos + len(data) / (self._nchannels * self._sampwidth)
  430.         return data
  431.  
  432.     
  433.     def _decomp_data(self, data):
  434.         import cl
  435.         dummy = self._decomp.SetParam(cl.FRAME_BUFFER_SIZE, len(data) * 2)
  436.         return self._decomp.Decompress(len(data) / self._nchannels, data)
  437.  
  438.     
  439.     def _ulaw2lin(self, data):
  440.         import audioop
  441.         return audioop.ulaw2lin(data, 2)
  442.  
  443.     
  444.     def _adpcm2lin(self, data):
  445.         import audioop
  446.         if not hasattr(self, '_adpcmstate'):
  447.             self._adpcmstate = None
  448.         
  449.         (data, self._adpcmstate) = audioop.adpcm2lin(data, 2, self._adpcmstate)
  450.         return data
  451.  
  452.     
  453.     def _read_comm_chunk(self, chunk):
  454.         self._nchannels = _read_short(chunk)
  455.         self._nframes = _read_long(chunk)
  456.         self._sampwidth = (_read_short(chunk) + 7) / 8
  457.         self._framerate = int(_read_float(chunk))
  458.         self._framesize = self._nchannels * self._sampwidth
  459.         if self._aifc:
  460.             kludge = 0
  461.             if chunk.chunksize == 18:
  462.                 kludge = 1
  463.                 print 'Warning: bad COMM chunk size'
  464.                 chunk.chunksize = 23
  465.             
  466.             self._comptype = chunk.read(4)
  467.             if kludge:
  468.                 length = ord(chunk.file.read(1))
  469.                 if length & 1 == 0:
  470.                     length = length + 1
  471.                 
  472.                 chunk.chunksize = chunk.chunksize + length
  473.                 chunk.file.seek(-1, 1)
  474.             
  475.             self._compname = _read_string(chunk)
  476.             if self._comptype != 'NONE':
  477.                 if self._comptype == 'G722':
  478.                     
  479.                     try:
  480.                         import audioop
  481.                     except ImportError:
  482.                         pass
  483.  
  484.                     self._convert = self._adpcm2lin
  485.                     self._framesize = self._framesize / 4
  486.                     return None
  487.                 self._comptype == 'G722'
  488.                 
  489.                 try:
  490.                     import cl
  491.                 except ImportError:
  492.                     if self._comptype == 'ULAW':
  493.                         
  494.                         try:
  495.                             import audioop
  496.                             self._convert = self._ulaw2lin
  497.                             self._framesize = self._framesize / 2
  498.                             return None
  499.                         except ImportError:
  500.                             pass
  501.                         except:
  502.                             None<EXCEPTION MATCH>ImportError
  503.                         
  504.  
  505.                     None<EXCEPTION MATCH>ImportError
  506.                     raise Error, 'cannot read compressed AIFF-C files'
  507.  
  508.                 if self._comptype == 'ULAW':
  509.                     scheme = cl.G711_ULAW
  510.                     self._framesize = self._framesize / 2
  511.                 elif self._comptype == 'ALAW':
  512.                     scheme = cl.G711_ALAW
  513.                     self._framesize = self._framesize / 2
  514.                 else:
  515.                     raise Error, 'unsupported compression type'
  516.                 self._decomp = (self._comptype == 'ULAW').OpenDecompressor(scheme)
  517.                 self._convert = self._decomp_data
  518.             
  519.         else:
  520.             self._comptype = 'NONE'
  521.             self._compname = 'not compressed'
  522.  
  523.     
  524.     def _readmark(self, chunk):
  525.         nmarkers = _read_short(chunk)
  526.         
  527.         try:
  528.             for i in range(nmarkers):
  529.                 id = _read_short(chunk)
  530.                 pos = _read_long(chunk)
  531.                 name = _read_string(chunk)
  532.                 if pos or name:
  533.                     self._markers.append((id, pos, name))
  534.                     continue
  535.         except EOFError:
  536.             print 'Warning: MARK chunk contains only', len(self._markers),
  537.             if len(self._markers) == 1:
  538.                 print 'marker',
  539.             else:
  540.                 print 'markers',
  541.             print 'instead of', nmarkers
  542.  
  543.  
  544.  
  545.  
  546. class Aifc_write:
  547.     
  548.     def __init__(self, f):
  549.         if type(f) == type(''):
  550.             filename = f
  551.             f = __builtin__.open(f, 'wb')
  552.         else:
  553.             filename = '???'
  554.         self.initfp(f)
  555.         if filename[-5:] == '.aiff':
  556.             self._aifc = 0
  557.         else:
  558.             self._aifc = 1
  559.  
  560.     
  561.     def initfp(self, file):
  562.         self._file = file
  563.         self._version = _AIFC_version
  564.         self._comptype = 'NONE'
  565.         self._compname = 'not compressed'
  566.         self._comp = None
  567.         self._convert = None
  568.         self._nchannels = 0
  569.         self._sampwidth = 0
  570.         self._framerate = 0
  571.         self._nframes = 0
  572.         self._nframeswritten = 0
  573.         self._datawritten = 0
  574.         self._datalength = 0
  575.         self._markers = []
  576.         self._marklength = 0
  577.         self._aifc = 1
  578.  
  579.     
  580.     def __del__(self):
  581.         if self._file:
  582.             self.close()
  583.         
  584.  
  585.     
  586.     def aiff(self):
  587.         if self._nframeswritten:
  588.             raise Error, 'cannot change parameters after starting to write'
  589.         self._nframeswritten
  590.         self._aifc = 0
  591.  
  592.     
  593.     def aifc(self):
  594.         if self._nframeswritten:
  595.             raise Error, 'cannot change parameters after starting to write'
  596.         self._nframeswritten
  597.         self._aifc = 1
  598.  
  599.     
  600.     def setnchannels(self, nchannels):
  601.         if self._nframeswritten:
  602.             raise Error, 'cannot change parameters after starting to write'
  603.         self._nframeswritten
  604.         if nchannels < 1:
  605.             raise Error, 'bad # of channels'
  606.         nchannels < 1
  607.         self._nchannels = nchannels
  608.  
  609.     
  610.     def getnchannels(self):
  611.         if not self._nchannels:
  612.             raise Error, 'number of channels not set'
  613.         self._nchannels
  614.         return self._nchannels
  615.  
  616.     
  617.     def setsampwidth(self, sampwidth):
  618.         if self._nframeswritten:
  619.             raise Error, 'cannot change parameters after starting to write'
  620.         self._nframeswritten
  621.         if sampwidth < 1 or sampwidth > 4:
  622.             raise Error, 'bad sample width'
  623.         sampwidth > 4
  624.         self._sampwidth = sampwidth
  625.  
  626.     
  627.     def getsampwidth(self):
  628.         if not self._sampwidth:
  629.             raise Error, 'sample width not set'
  630.         self._sampwidth
  631.         return self._sampwidth
  632.  
  633.     
  634.     def setframerate(self, framerate):
  635.         if self._nframeswritten:
  636.             raise Error, 'cannot change parameters after starting to write'
  637.         self._nframeswritten
  638.         if framerate <= 0:
  639.             raise Error, 'bad frame rate'
  640.         framerate <= 0
  641.         self._framerate = framerate
  642.  
  643.     
  644.     def getframerate(self):
  645.         if not self._framerate:
  646.             raise Error, 'frame rate not set'
  647.         self._framerate
  648.         return self._framerate
  649.  
  650.     
  651.     def setnframes(self, nframes):
  652.         if self._nframeswritten:
  653.             raise Error, 'cannot change parameters after starting to write'
  654.         self._nframeswritten
  655.         self._nframes = nframes
  656.  
  657.     
  658.     def getnframes(self):
  659.         return self._nframeswritten
  660.  
  661.     
  662.     def setcomptype(self, comptype, compname):
  663.         if self._nframeswritten:
  664.             raise Error, 'cannot change parameters after starting to write'
  665.         self._nframeswritten
  666.         if comptype not in ('NONE', 'ULAW', 'ALAW', 'G722'):
  667.             raise Error, 'unsupported compression type'
  668.         comptype not in ('NONE', 'ULAW', 'ALAW', 'G722')
  669.         self._comptype = comptype
  670.         self._compname = compname
  671.  
  672.     
  673.     def getcomptype(self):
  674.         return self._comptype
  675.  
  676.     
  677.     def getcompname(self):
  678.         return self._compname
  679.  
  680.     
  681.     def setparams(self, info):
  682.         (nchannels, sampwidth, framerate, nframes, comptype, compname) = info
  683.         if self._nframeswritten:
  684.             raise Error, 'cannot change parameters after starting to write'
  685.         self._nframeswritten
  686.         if comptype not in ('NONE', 'ULAW', 'ALAW', 'G722'):
  687.             raise Error, 'unsupported compression type'
  688.         comptype not in ('NONE', 'ULAW', 'ALAW', 'G722')
  689.         self.setnchannels(nchannels)
  690.         self.setsampwidth(sampwidth)
  691.         self.setframerate(framerate)
  692.         self.setnframes(nframes)
  693.         self.setcomptype(comptype, compname)
  694.  
  695.     
  696.     def getparams(self):
  697.         if not (self._nchannels) and not (self._sampwidth) or not (self._framerate):
  698.             raise Error, 'not all parameters set'
  699.         not (self._framerate)
  700.         return (self._nchannels, self._sampwidth, self._framerate, self._nframes, self._comptype, self._compname)
  701.  
  702.     
  703.     def setmark(self, id, pos, name):
  704.         if id <= 0:
  705.             raise Error, 'marker ID must be > 0'
  706.         id <= 0
  707.         if pos < 0:
  708.             raise Error, 'marker position must be >= 0'
  709.         pos < 0
  710.         if type(name) != type(''):
  711.             raise Error, 'marker name must be a string'
  712.         type(name) != type('')
  713.         for i in range(len(self._markers)):
  714.             if id == self._markers[i][0]:
  715.                 self._markers[i] = (id, pos, name)
  716.                 return None
  717.         
  718.         self._markers.append((id, pos, name))
  719.  
  720.     
  721.     def getmark(self, id):
  722.         for marker in self._markers:
  723.             if id == marker[0]:
  724.                 return marker
  725.         
  726.         raise Error, 'marker %r does not exist' % (id,)
  727.  
  728.     
  729.     def getmarkers(self):
  730.         if len(self._markers) == 0:
  731.             return None
  732.         return self._markers
  733.  
  734.     
  735.     def tell(self):
  736.         return self._nframeswritten
  737.  
  738.     
  739.     def writeframesraw(self, data):
  740.         self._ensure_header_written(len(data))
  741.         nframes = len(data) / (self._sampwidth * self._nchannels)
  742.         if self._convert:
  743.             data = self._convert(data)
  744.         
  745.         self._file.write(data)
  746.         self._nframeswritten = self._nframeswritten + nframes
  747.         self._datawritten = self._datawritten + len(data)
  748.  
  749.     
  750.     def writeframes(self, data):
  751.         self.writeframesraw(data)
  752.         if self._nframeswritten != self._nframes or self._datalength != self._datawritten:
  753.             self._patchheader()
  754.         
  755.  
  756.     
  757.     def close(self):
  758.         self._ensure_header_written(0)
  759.         if self._datawritten & 1:
  760.             self._file.write(chr(0))
  761.             self._datawritten = self._datawritten + 1
  762.         
  763.         self._writemarkers()
  764.         if self._nframeswritten != self._nframes and self._datalength != self._datawritten or self._marklength:
  765.             self._patchheader()
  766.         
  767.         if self._comp:
  768.             self._comp.CloseCompressor()
  769.             self._comp = None
  770.         
  771.         self._file.flush()
  772.         self._file = None
  773.  
  774.     
  775.     def _comp_data(self, data):
  776.         import cl
  777.         dummy = self._comp.SetParam(cl.FRAME_BUFFER_SIZE, len(data))
  778.         dummy = self._comp.SetParam(cl.COMPRESSED_BUFFER_SIZE, len(data))
  779.         return self._comp.Compress(self._nframes, data)
  780.  
  781.     
  782.     def _lin2ulaw(self, data):
  783.         import audioop
  784.         return audioop.lin2ulaw(data, 2)
  785.  
  786.     
  787.     def _lin2adpcm(self, data):
  788.         import audioop
  789.         if not hasattr(self, '_adpcmstate'):
  790.             self._adpcmstate = None
  791.         
  792.         (data, self._adpcmstate) = audioop.lin2adpcm(data, 2, self._adpcmstate)
  793.         return data
  794.  
  795.     
  796.     def _ensure_header_written(self, datasize):
  797.         if not self._nframeswritten:
  798.             if self._comptype in ('ULAW', 'ALAW'):
  799.                 if not self._sampwidth:
  800.                     self._sampwidth = 2
  801.                 
  802.                 if self._sampwidth != 2:
  803.                     raise Error, 'sample width must be 2 when compressing with ULAW or ALAW'
  804.                 self._sampwidth != 2
  805.             
  806.             if self._comptype == 'G722':
  807.                 if not self._sampwidth:
  808.                     self._sampwidth = 2
  809.                 
  810.                 if self._sampwidth != 2:
  811.                     raise Error, 'sample width must be 2 when compressing with G7.22 (ADPCM)'
  812.                 self._sampwidth != 2
  813.             
  814.             if not self._nchannels:
  815.                 raise Error, '# channels not specified'
  816.             self._nchannels
  817.             if not self._sampwidth:
  818.                 raise Error, 'sample width not specified'
  819.             self._sampwidth
  820.             if not self._framerate:
  821.                 raise Error, 'sampling rate not specified'
  822.             self._framerate
  823.             self._write_header(datasize)
  824.         
  825.  
  826.     
  827.     def _init_compression(self):
  828.         if self._comptype == 'G722':
  829.             self._convert = self._lin2adpcm
  830.             return None
  831.         
  832.         try:
  833.             import cl
  834.         except ImportError:
  835.             self._comptype == 'G722'
  836.             self._comptype == 'G722'
  837.             if self._comptype == 'ULAW':
  838.                 
  839.                 try:
  840.                     import audioop
  841.                     self._convert = self._lin2ulaw
  842.                     return None
  843.                 except ImportError:
  844.                     pass
  845.                 except:
  846.                     None<EXCEPTION MATCH>ImportError
  847.                 
  848.  
  849.             None<EXCEPTION MATCH>ImportError
  850.             raise Error, 'cannot write compressed AIFF-C files'
  851.         except:
  852.             self._comptype == 'G722'
  853.  
  854.         if self._comptype == 'ULAW':
  855.             scheme = cl.G711_ULAW
  856.         elif self._comptype == 'ALAW':
  857.             scheme = cl.G711_ALAW
  858.         else:
  859.             raise Error, 'unsupported compression type'
  860.         self._comp = (self._comptype == 'G722').OpenCompressor(scheme)
  861.         params = [
  862.             cl.ORIGINAL_FORMAT,
  863.             0,
  864.             cl.BITS_PER_COMPONENT,
  865.             self._sampwidth * 8,
  866.             cl.FRAME_RATE,
  867.             self._framerate,
  868.             cl.FRAME_BUFFER_SIZE,
  869.             100,
  870.             cl.COMPRESSED_BUFFER_SIZE,
  871.             100]
  872.         if self._nchannels == 1:
  873.             params[1] = cl.MONO
  874.         elif self._nchannels == 2:
  875.             params[1] = cl.STEREO_INTERLEAVED
  876.         else:
  877.             raise Error, 'cannot compress more than 2 channels'
  878.         (self._nchannels == 1)._comp.SetParams(params)
  879.         dummy = self._comp.Compress(0, '')
  880.         self._convert = self._comp_data
  881.  
  882.     
  883.     def _write_header(self, initlength):
  884.         if self._aifc and self._comptype != 'NONE':
  885.             self._init_compression()
  886.         
  887.         self._file.write('FORM')
  888.         if not self._nframes:
  889.             self._nframes = initlength / (self._nchannels * self._sampwidth)
  890.         
  891.         self._datalength = self._nframes * self._nchannels * self._sampwidth
  892.         if self._datalength & 1:
  893.             self._datalength = self._datalength + 1
  894.         
  895.         if self._aifc:
  896.             if self._comptype in ('ULAW', 'ALAW'):
  897.                 self._datalength = self._datalength / 2
  898.                 if self._datalength & 1:
  899.                     self._datalength = self._datalength + 1
  900.                 
  901.             elif self._comptype == 'G722':
  902.                 self._datalength = (self._datalength + 3) / 4
  903.                 if self._datalength & 1:
  904.                     self._datalength = self._datalength + 1
  905.                 
  906.             
  907.         
  908.         self._form_length_pos = self._file.tell()
  909.         commlength = self._write_form_length(self._datalength)
  910.         if self._aifc:
  911.             self._file.write('AIFC')
  912.             self._file.write('FVER')
  913.             _write_long(self._file, 4)
  914.             _write_long(self._file, self._version)
  915.         else:
  916.             self._file.write('AIFF')
  917.         self._file.write('COMM')
  918.         _write_long(self._file, commlength)
  919.         _write_short(self._file, self._nchannels)
  920.         self._nframes_pos = self._file.tell()
  921.         _write_long(self._file, self._nframes)
  922.         _write_short(self._file, self._sampwidth * 8)
  923.         _write_float(self._file, self._framerate)
  924.         if self._aifc:
  925.             self._file.write(self._comptype)
  926.             _write_string(self._file, self._compname)
  927.         
  928.         self._file.write('SSND')
  929.         self._ssnd_length_pos = self._file.tell()
  930.         _write_long(self._file, self._datalength + 8)
  931.         _write_long(self._file, 0)
  932.         _write_long(self._file, 0)
  933.  
  934.     
  935.     def _write_form_length(self, datalength):
  936.         if self._aifc:
  937.             commlength = 23 + len(self._compname)
  938.             if commlength & 1:
  939.                 commlength = commlength + 1
  940.             
  941.             verslength = 12
  942.         else:
  943.             commlength = 18
  944.             verslength = 0
  945.         _write_long(self._file, 4 + verslength + self._marklength + 8 + commlength + 16 + datalength)
  946.         return commlength
  947.  
  948.     
  949.     def _patchheader(self):
  950.         curpos = self._file.tell()
  951.         if self._datawritten & 1:
  952.             datalength = self._datawritten + 1
  953.             self._file.write(chr(0))
  954.         else:
  955.             datalength = self._datawritten
  956.         if datalength == self._datalength and self._nframes == self._nframeswritten and self._marklength == 0:
  957.             self._file.seek(curpos, 0)
  958.             return None
  959.         self._file.seek(self._form_length_pos, 0)
  960.         dummy = self._write_form_length(datalength)
  961.         self._file.seek(self._nframes_pos, 0)
  962.         _write_long(self._file, self._nframeswritten)
  963.         self._file.seek(self._ssnd_length_pos, 0)
  964.         _write_long(self._file, datalength + 8)
  965.         self._file.seek(curpos, 0)
  966.         self._nframes = self._nframeswritten
  967.         self._datalength = datalength
  968.  
  969.     
  970.     def _writemarkers(self):
  971.         if len(self._markers) == 0:
  972.             return None
  973.         self._file.write('MARK')
  974.         length = 2
  975.         for marker in self._markers:
  976.             (id, pos, name) = marker
  977.             length = length + len(name) + 1 + 6
  978.             if len(name) & 1 == 0:
  979.                 length = length + 1
  980.                 continue
  981.             len(self._markers) == 0
  982.         
  983.         _write_long(self._file, length)
  984.         self._marklength = length + 8
  985.         _write_short(self._file, len(self._markers))
  986.         for marker in self._markers:
  987.             (id, pos, name) = marker
  988.             _write_short(self._file, id)
  989.             _write_long(self._file, pos)
  990.             _write_string(self._file, name)
  991.         
  992.  
  993.  
  994.  
  995. def open(f, mode = None):
  996.     if mode is None:
  997.         if hasattr(f, 'mode'):
  998.             mode = f.mode
  999.         else:
  1000.             mode = 'rb'
  1001.     
  1002.     if mode in ('r', 'rb'):
  1003.         return Aifc_read(f)
  1004.     if mode in ('w', 'wb'):
  1005.         return Aifc_write(f)
  1006.     raise Error, "mode must be 'r', 'rb', 'w', or 'wb'"
  1007.  
  1008. openfp = open
  1009. if __name__ == '__main__':
  1010.     import sys
  1011.     if not sys.argv[1:]:
  1012.         sys.argv.append('/usr/demos/data/audio/bach.aiff')
  1013.     
  1014.     fn = sys.argv[1]
  1015.     f = open(fn, 'r')
  1016.     print 'Reading', fn
  1017.     print 'nchannels =', f.getnchannels()
  1018.     print 'nframes   =', f.getnframes()
  1019.     print 'sampwidth =', f.getsampwidth()
  1020.     print 'framerate =', f.getframerate()
  1021.     print 'comptype  =', f.getcomptype()
  1022.     print 'compname  =', f.getcompname()
  1023.     if sys.argv[2:]:
  1024.         gn = sys.argv[2]
  1025.         print 'Writing', gn
  1026.         g = open(gn, 'w')
  1027.         g.setparams(f.getparams())
  1028.         while None:
  1029.             data = f.readframes(1024)
  1030.             if not data:
  1031.                 break
  1032.             
  1033.             continue
  1034.             g.close()
  1035.             f.close()
  1036.             print 'Done.'
  1037.     sys.argv[2:]
  1038.  
  1039.